package repository

import (
	"context"
	"fmt"
	"time"

	"github.com/redis/go-redis/v9"
	"good.house/internal/constan"
	"good.house/internal/model"
	"gorm.io/gorm"
)

type IUserRepository interface {
	Create(user *model.User) error
	Delete(id int64) error
	Update(user *model.User) error
	FindUserById(id int64) (user *model.User, err error)
	FindUserByUsername(userName string) (user *model.User, err error)
	GetCountByUsername(username string) int64
	GetCountByMobile(mobile string) int64

	SetTokenId(tokenId string) error
	HasTokenId(tokenId string) bool
}

type UserRepository struct {
	db  *gorm.DB
	rdb *redis.Client
	ctx context.Context
}

func NewUserRepository(db *gorm.DB, rdb *redis.Client) *UserRepository {
	return &UserRepository{
		db:  db,
		rdb: rdb,
		ctx: context.Background(),
	}
}

func (r *UserRepository) Create(user *model.User) error {
	res := r.db.Create(user)

	return res.Error
}

func (r *UserRepository) GetCountByUsername(username string) int64 {
	var count int64
	r.db.Model(&model.User{}).Where("username = ?", username).Count(&count)

	return count
}

func (r *UserRepository) GetCountByMobile(mobile string) int64 {
	var count int64
	r.db.Model(&model.User{}).Where("mobile = ?", mobile).Count(&count)
	return count
}

func (r *UserRepository) Delete(id int64) error {
	res := r.db.Delete(&model.User{}, id)

	return res.Error
}

func (r *UserRepository) Update(user *model.User) error {
	res := r.db.Save(user)

	return res.Error
}

func (r *UserRepository) FindUserById(id int64) (user *model.User, err error) {
	res := r.db.First(user, id)

	return user, res.Error
}

func (r *UserRepository) FindUserByUsername(username string) (user *model.User, err error) {
	user = &model.User{}
	res := r.db.Where("username = ?", username).Find(user)

	return user, res.Error
}

func (r *UserRepository) SetTokenId(tokenId string) error {
	res := r.rdb.Set(r.ctx, fmt.Sprintf("%s:%s", constan.RedisTokenIdsPrefix, tokenId), tokenId, time.Hour)

	return res.Err()
}

func (r *UserRepository) HasTokenId(tokenId string) bool {
	res := r.rdb.Get(r.ctx, fmt.Sprintf("%s:%s", constan.RedisTokenIdsPrefix, tokenId))

	return res.Err() == nil
}
